package com.settlement.system.common.util.common;

import jakarta.validation.constraints.NotNull;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.Nullable;

import java.util.*;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;


/**
 * 描述: 字符串工具,StringUtils增强
 * @author hc
 */
public class StrUtil {
	private static final String BLANK="";
	private static final String BRACE="{}";
	private static final String GET="get";
	private static final String IS="is";

	private StrUtil(){}

	public static boolean startsWithIgnoreCase(final String sequence, final String... searchStrings){
		if(StringUtils.isBlank(sequence)){
			return false;
		}
		if(searchStrings==null||searchStrings.length<1){
			return false;
		}
		for(String str:searchStrings){
			if(StringUtils.startsWithIgnoreCase(sequence,str)){
				return true;
			}
		}
		return false;
	}
	/**
	 * 将字符串首字母小写
	 * @param str 字符串
	 * @return 将字符串首字母小写
	 */
	public static String lowerFirst(String str) {
		if (str == null || ( str.length()) == 0) {
			return str;
		}

		char ch = str.charAt(0);
		if(Character.isUpperCase(ch)){
			char[] chars=str.toCharArray();
			chars[0]=Character.toLowerCase(chars[0]);
			return new String(chars);
		}else{
			return str;
		}
	}
	/**
	 * 将字符串首字母大写
	 * @param str 字符串
	 * @return 将字符串首字母大写
	 */
	public static String upperFirst(String str) {
		if (str == null || ( str.length()) == 0) {
			return str;
		}

		char ch = str.charAt(0);
		if(Character.isLowerCase(ch)){
			char[] chars=str.toCharArray();
			chars[0]=Character.toUpperCase(chars[0]);
			return new String(chars);
		}else{
			return str;
		}
	}

	/**
	 * 获取长度<br>
	 * 是String类型的时候会去掉空白
	 * @param target 文本
	 * @return 获取长度
	 */
	public static int length(CharSequence target){
		if(target==null){
			return 0;
		}
		if(target instanceof String){
			return StringUtils.trimToEmpty( (String) target ).length();
		}

		return target.length();
	}

	/**
	 * 按照参数格式化返回字符串,会将{}转换成%s
	 * @param format 格式化字符串
	 * @param args 参数
	 * @return 按照参数格式化返回字符串
	 */
	public static String format(String format, Object... args){
		if(StringUtils.isBlank( format ) || args==null ||args.length<1){
			return format;
		}
		if(StringUtils.contains(format,BRACE)){
			format=StringUtils.replace(format, BRACE, "%s");
		}
		return String.format(format,args);
	}

	/**
	 * 如果是get/is方法,返回字段名
	 * @param methodName 方法名
	 * @return 方法对于字段名
	 */
	public static String resolveFieldName(String methodName) {
		if (methodName.startsWith(GET)) {
			methodName = methodName.substring(3);
		} else if (methodName.startsWith(IS)) {
			methodName = methodName.substring(2);
		}

		return lowerFirst(methodName);
	}

	/**
	 * 拼接字符串
	 * @param args 参数
	 * @return 字符串
	 */
	public static String append(Object... args){
		if(args==null||args.length<1){
			return BLANK;
		}
		StringBuilder builder=new StringBuilder();
		Arrays.stream(args).filter(Objects::nonNull).forEach(builder::append);
		return builder.toString();
	}
	/**
	 * 拼接字符串
	 * @param builder builder
	 * @param args 参数
	 * @return 字符串
	 * @see this#appendBuilder(StringBuilder, Object...)
	 */
	public static StringBuilder append(StringBuilder builder,Object... args){
		return appendBuilder(builder,args);
	}
	/**
	 * 拼接字符串
	 * @param builder builder
	 * @param args 参数
	 * @return 字符串
	 */
	public static StringBuilder appendBuilder(StringBuilder builder,Object... args){
		return appendBuilderIf(builder,true,args);
	}
	/**
	 * 拼接字符串
	 * @param builder builder
	 * @param args 参数
	 * @param predicate 条件true,执行,false 不执行
	 * @return 字符串
	 */
	public static <T> StringBuilder appendBuilderIf(StringBuilder builder, boolean predicate,Object... args){
		if(args==null||args.length<1 || !predicate){
			return builder;
		}

		Arrays.stream(args).filter(Objects::nonNull).forEach(builder::append );
		return builder;
	}
	/**
	 * 拼接字符串,只要有null的不添加进去
	 * @param builder builder
	 * @param args 参数
	 */
	public static <T> void appendBuilderNotNull(StringBuilder builder, Object... args){
		if(args==null||args.length<1 ){
			return;
		}
		if(Arrays.stream(args).anyMatch(Objects::nonNull)){
			return;
		}
		Arrays.stream(args).filter(Objects::nonNull).forEach(builder::append );
	}
	/**
	 * 去掉builder最后一个字符
	 * @param builder StringBuilder
	 */
	public static void removeLastChar(StringBuilder builder){
		if(builder!=null && builder.length()>0){
			builder.setLength(builder.length()-1);
		}
	}


	/**
	 * 描述：返回当前所以的实体对象
	 * @param array 数组
	 * @return 字符串
	 * org.apache.commons.lang3.StringUtils.join(Object[],char)
	 */
	@NotNull
	public static String toString(@Nullable Object... array){
		if (array == null||array.length<1){
			return "";
		}
		return StringUtils.join(array,',');
	}

	/**
	 * 描述：返回当前所以的实体对象
	 * @param array 数组
	 * @return 字符串
	 * org.apache.commons.lang3.StringUtils.join(Object[],char)
	 */
	@NotNull
	public static String join(@Nullable Object... array){
		if (array == null||array.length<1){
			return "";
		}
		return StringUtils.join(array,null);
	}

	/**
	 * 描述：返回当前所以的实体对象
	 * @param separator 分隔符,为空表示没有分隔符
	 * @param array 数组
	 * @return 字符串
	 * org.apache.commons.lang3.StringUtils.join(Object[],char)
	 */
	@NotNull
	public static String joinWith(final char separator,@Nullable Object... array){
		if (array == null||array.length<1){
			return "";
		}
		return StringUtils.join(array,separator);
	}

	/**
	 * 描述：拼接当前数组
	 * @param func 获取字段函数
	 * @param lists 数组
	 * @param <T> 实体泛型
	 * @return 字符串
	 */
	@NotNull
	public static <T> String joinWith(List<T> lists , Function<? super T, String>  func) {
		return lists.stream().map(func).collect(Collectors.joining(","));
	}

	/**
	 * 描述：返回当前所以的实体对象
	 * @param separator 分隔符,为空表示没有分隔符
	 * @param array 数组
	 * @return 字符串
	 */
	@NotNull
	public static String joinNotNullWith(final char separator,@Nullable String... array){
		if (array == null||array.length<1){
			return null;
		}
		List<String> collect = Arrays.stream(array).filter(s -> StringUtils.isNotBlank(s)).collect(Collectors.toList());
		if(collect==null||collect.size()==0){
			return null;
		}
		return StringUtils.join(collect,separator);
	}

	/**
	 * 字符串转换成集合
	 * @param str 字符串
	 * @param separatorChar 分隔符
	 * @param inputFn 要保存的集合
	 * @param dv 默认值
	 * @param <C> 集合
	 * @return 字符串转换成集合
	 */
	public static <C extends Collection<String>> C splitToCollection(String str, char separatorChar, IntFunction<C> inputFn, Supplier<C> dv){
		if(StringUtils.isNotBlank(str)){
			String[] strings=StringUtils.split(str, separatorChar);
			C apply=inputFn.apply(strings.length);
			Collections.addAll(apply,strings);
			return apply;
		}else{
			return dv.get();
		}
	}
	/**
	 * 字符串分隔符','转换成集合
	 * splitToCollection(str,HashSet::new, Collections::emptySet);
	 * splitToCollection(str,LinkedHashSet::new, LinkedHashSet::new);
	 * @param str 字符串
	 * @param inputFn 要保存的集合
	 * @param dv 默认值
	 * @param <C> 集合
	 * @return 字符串转换成集合
	 */
	public static <C extends Collection<String>> C splitToCollection(String str, IntFunction<C> inputFn,Supplier<C> dv){
		if(StringUtils.isNotBlank(str)){
			String[] strings=StringUtils.split(str, ',');
			C apply=inputFn.apply(strings.length);
			Collections.addAll(apply,strings);
			return apply;
		}else{
			return dv.get();
		}
	}
	public static <C extends Collection<String>> C splitToCollection(String str, IntFunction<C> inputFn){
		if(StringUtils.isNotBlank(str)){
			String[] strings=StringUtils.split(str, ',');
			C apply=inputFn.apply(strings.length);
			Collections.addAll(apply,strings);
			return apply;
		}else{
			return inputFn.apply(16);
		}
	}
	public static <C extends Collection<String>> C splitNullToCollection(String str, IntFunction<C> inputFn){
		if(StringUtils.isNotBlank(str)){
			String[] strings=StringUtils.split(str, ',');
			C apply=inputFn.apply(strings.length);
			String[] aNull = Arrays.stream(strings).map((s) -> StringUtils.equals("null", s) ? null : s).toArray(String[]::new);
			Collections.addAll(apply,aNull);
			return apply;
		}else{
			return inputFn.apply(16);
		}
	}

	public static Set<String> splitToSet(String str){
		return splitToCollection(str,LinkedHashSet::new, Collections::emptySet);
	}
	public static Set<String> splitToNewSet(String str){
		return splitToCollection(str, LinkedHashSet::new);
	}

	/**
	 * 字符串转换成List
	 * @param str 字符串
	 * @param isReturnNew 为空时是否返回新的ArrayList对象
	 * @return 字符串转换成List
	 */
	public static List<String> splitToList(String str,boolean isReturnNew){
		if(isReturnNew){
			return splitToCollection(str, ArrayList::new);
		}
		return splitToCollection(str, ArrayList::new, Collections::emptyList);
	}

	/**
	 * 截取字符串中间的字段
	 * @param str 字符串
	 * @param before  获取字符串之前的字段值
	 * @param after   获取字符串之后的字段值
	 * @return
	 */
	public static String substringBetweenStr(String str,String before,String after){
		if(StringUtils.isBlank(str)){
			return null;
		}
		return StringUtils.substringAfter(StringUtils.substringBefore(str,before),after);
	}

	/**
	 * 校验字段
	 * @param supplier 校验字段
	 * @param condition 条件
	 * @param format 提示模板
	 * @param args 参数
	 * @param <T> 泛型
	 * @return 返回校验结果
	 */
	public static<T> String notNull(Supplier<T> supplier, Predicate<T> condition, String format, Object... args){
		if(condition.test(supplier.get())){
			return format(format,args);
		}
		return null;
	}

	/**
	 * 截取字符串最后一个字符之前的字符串
	 * @param builder 字符串
	 * @return 返回去掉最后一个字符的字符串
	 */
	public static String substringBuilderEnd(StringBuilder builder){
		return builder.toString().substring(0, builder.toString().length() - 1);
	}

	/**
	 * 拼接起始时间
	 * @param sqlScript 拼接sql
	 * @param table 表名
	 * @param newLine 是否换行
	 * @return 返回拼接sql
	 */
	public static String convertStartDate(String table, String sqlScript, boolean newLine) {
		String newSqlScript = sqlScript;
		if (newLine) {
			newSqlScript = "\n" + sqlScript + "\n";
		}
		return String.format(" AND TO_CHAR(%s.OUT_DATE,'yyyy-MM-dd') >='%s'", table, newSqlScript);
	}


	/**
	 * 拼接结束时间
	 * @param sqlScript 拼接sql
	 * @param table 表名
	 * @param newLine 是否换行
	 * @return 返回拼接sql
	 */
	public static String convertEndDate(String table, String sqlScript, boolean newLine) {
		String newSqlScript = sqlScript;
		if (newLine) {
			newSqlScript = "\n" + sqlScript + "\n";
		}
		return String.format(" AND TO_CHAR(%s.OUT_DATE,'yyyy-MM-dd hh24:mi:ss') <='%s 23:59:59' AND %s.STATUS=1 ", table, newSqlScript,table);
	}



}
